/**
 *
 * @author John Creecy
 */
package server;

import server.entities.PlayerActionEntity;
import java.lang.management.ManagementFactory;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

public class BattleBarn {

	public static ConcurrentHashMap<String, Long> clientList = new ConcurrentHashMap<String, Long>();
	public static ConcurrentHashMap<String, PlayerActionEntity> actionStack = new ConcurrentHashMap<String, PlayerActionEntity>();
	public static Vector<PlayerActionEntity> gameState = new Vector<PlayerActionEntity>();
	public static ArrayBlockingQueue<Runnable> processorWorkQueue = new ArrayBlockingQueue<Runnable>(10000);
	public static ArrayBlockingQueue<Runnable> stateGeneratorWorkQueue = new ArrayBlockingQueue<Runnable>(10000);

	public static int packetsIn;
	public static int packetsInSnapshot;
	public static int packetsOut;

	static ThreadPoolExecutor processorThreadPool;
	public final ScheduledExecutorService stateGeneratorThreadPool = Executors.newScheduledThreadPool(1);
	public final ScheduledExecutorService staleClientsThreadPool = Executors.newScheduledThreadPool(1);

	public void start() {
		initJMX();

		packetsInSnapshot = 0;
		packetsIn = 0;
		packetsOut = 0;

		processorThreadPool = new ThreadPoolExecutor(1, 2, 10, TimeUnit.SECONDS, processorWorkQueue);
		stateGeneratorThreadPool.scheduleAtFixedRate(new StateGenerator(), 100, 100, TimeUnit.MILLISECONDS);
		staleClientsThreadPool.scheduleAtFixedRate(new FlushStaleClients(), 30, 30, TimeUnit.SECONDS);

		Runnable runnable = new GameListener();
		Thread thread = new Thread(runnable);
		thread.start();
	}

	public static void addProcessorTask(Runnable task) {
		processorThreadPool.execute(task);
	}

	private void initJMX() {
		try {
			MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
			ObjectName mbeanName = new ObjectName("com.battlebarn:type=status");
			BattleBarnJMX mbean = new BattleBarnJMX();
			mbs.registerMBean(mbean, mbeanName);
		} catch (InstanceAlreadyExistsException ex) {
			Logger.getLogger(BattleBarn.class.getName()).log(Level.SEVERE, null, ex);
		} catch (MBeanRegistrationException ex) {
			Logger.getLogger(BattleBarn.class.getName()).log(Level.SEVERE, null, ex);
		} catch (NotCompliantMBeanException ex) {
			Logger.getLogger(BattleBarn.class.getName()).log(Level.SEVERE, null, ex);
		} catch (MalformedObjectNameException ex) {
			Logger.getLogger(BattleBarn.class.getName()).log(Level.SEVERE, null, ex);
		} catch (NullPointerException ex) {
			Logger.getLogger(BattleBarn.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

	public static void main(String[] args) {
		BattleBarn battleBarn = new BattleBarn();
		battleBarn.start();
	}
}
